package com.raojunxue.company.util;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.ServletActionContext;

import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;

/**
 * common action utility for action layer.
 * 
 * @author dony.xie
 * 
 */
public class ActionUtil {

	private static Log log = LogFactory.getFactory().getInstance(
			ActionUtil.class);
	
	private static final String WL_PROXY_CLIENT_IP = "WL-Proxy-Client-IP";
    private static final String PROXY_CLIENT_IP = "Proxy-Client-IP";
    private static final String UNKNOWN = "unknown";
	
	/**
	 * get object from HttpRequest's session with the given sessionKey.
	 * 
	 * @param sessionKey
	 * @return
	 */
	public static Object getSession(String sessionKey) {
		return ServletActionContext.getRequest().getSession().getAttribute(
				sessionKey);
	}

	/**
	 * input object into HttpRequest's session.
	 * 
	 * @param key
	 * @param value
	 */
	public static void setSession(String key, Object value) {
		ServletActionContext.getRequest().getSession().setAttribute(key, value);
	}

	/**
	 * get object from HttpRequest's attribute with the given attributeKey.
	 * 
	 * @param sessionKey
	 * @return
	 */
	public static Object getAttribute(String sessionKey) {
		return ServletActionContext.getRequest().getAttribute(sessionKey);
	}

	/**
	 * input object into HttpRequest's attribute.
	 * 
	 * @param key
	 * @param value
	 */
	public static void setAttribute(String key, Object value) {
		ServletActionContext.getRequest().setAttribute(key, value);
	}

	/**
	 * remove object from session which mapping to the given key.
	 * 
	 * @param sessionKey
	 */
	public static void removeSession(String sessionKey) {
		ServletActionContext.getRequest().getSession().removeAttribute(
				sessionKey);
	}

	/**
	 * get parameter value from HttpRequest
	 * 
	 * @param requestKey
	 * @return
	 */
	public static String getRequestParameter(String requestKey) {
		return ServletActionContext.getRequest().getParameter(requestKey);
	}

	public static Object saveConditionSessionKey(Object object){
		if (ActionUtil.getRequestParameter("pageNo") == null) {
			ActionUtil.setSession("searchDto", object);
		} else {
			object = ActionUtil.getSession("searchDto");
		}
		return object;
	}

	/**
	 * write message into response with UTF-8 encoding.
	 * 
	 * @param message
	 * @throws IOException
	 */
	public static void writeResponse(String message) {

		log.debug("write message into response using UTF-8 encoding:\n\t " + message);

		ServletActionContext.getResponse().setContentType("text/html; charset=UTF-8");
		ServletActionContext.getResponse().setHeader("Charset", "UTF-8");
		ServletActionContext.getResponse().setCharacterEncoding("UTF-8");
		try {
			ServletActionContext.getResponse().getWriter().write(message);
		} catch (IOException e) {
			log.error("write message to response failed.");
			log.info(e.getMessage());
		}
	}

	/**
	 * get parameter values from HttpRequest
	 * 
	 * @param paramKey
	 * @param requestKey
	 */
	public static String[] getRequestParameterValues(String paramKey) {
		return ServletActionContext.getRequest().getParameterValues(paramKey);
	}
	
	public static HttpServletRequest getHttpRequest() {
		return ServletActionContext.getRequest();
	}
	
	@SuppressWarnings("deprecation")
	public static String getContextRealPath() {
		return ServletActionContext.getRequest().getRealPath("/");
	}

	@SuppressWarnings("unchecked")
	public static Map<String, String[]> getRequestParameterMap() {
		return ServletActionContext.getRequest().getParameterMap();
	}
	
	public static String arrayToString(String str[]){
		StringBuffer temStr  = new StringBuffer();
		for(int i =0; i < str.length; i ++){
			temStr.append(str[i]);
			temStr.append("$");
		}
		return temStr.toString();
	}
	
	public static String[] stringToArray(String str){
		String[] temStr = str.split("$");
		return temStr;
	}

	
	private static void writeJson(Iterator<? extends Object> s1, String[] s2, StringBuffer buf) {
		while(s1.hasNext()) {
			buf.append("{");
			Object obj = s1.next();
			for(String s: s2) {
				Method mtd = getMethod(obj.getClass(), s);
				if(mtd != null) {
					Object value;
					try {
						value = mtd.invoke(obj, new Object[]{});
						buf.append(s+ ":'" + value.toString() +"',");
					} catch (IllegalArgumentException e) {
						log.info(e.getMessage());
					} catch (IllegalAccessException e) {
						log.info(e.getMessage());
					} catch (InvocationTargetException e) {
						log.info(e.getMessage());
					}
				}
			}
			buf.append("END:'END'},");
		}
	}
	
	private static Method getMethod(Class<?> cls, String name) {
		try{
			Method[] mtds = cls.getMethods();
			for(Method mtd : mtds) {
				String mtdName = mtd.getName();
				if(mtdName.equalsIgnoreCase("get"+name)) {
					return mtd;
				}
				if(mtdName.equalsIgnoreCase("is"+name)) {
					return mtd;
				}
			}
			return null;
		} catch (SecurityException e) {
			return null;
		}
	}

	public static String toJsonString(Iterator<? extends Object> s1, String[] s2) {
		StringBuffer buffer = new StringBuffer();
		buffer.append("[");
		writeJson(s1, s2, buffer);
		buffer.append("null]");
		return buffer.toString();
	}
	
	@SuppressWarnings("unchecked")
	public static Object getProperty(Object o, String name) {
		if(o == null)
			return null;
		Class[] cs = {};
		Object[] os = {};
		String methodName = buildName(name,"get");
		Object property = invoke(o, methodName, cs, os);
		return property;
	}
	
	@SuppressWarnings("unchecked")
	public static Object getProperty(Object o, String name, boolean bool) {
		if(o == null)
			return null;
		Class[] cs = {};
		Object[] os = {};
		String methodName = null;
		if(bool)
			methodName = buildName(name,"is");
		else
			methodName = buildName(name,"get");
		Object property = invoke(o, methodName, cs, os);
		return property;
	}

	@SuppressWarnings("unchecked")
	private static Object invoke(Object o, String methodName, Class[] cs, Object[] os) {
		try {
			System.out.println(methodName);
			Method method = o.getClass().getMethod(methodName,
					cs);
			if(method != null){
				Object value = method.invoke(o, os);
				return value;
			}
		} catch (SecurityException e) {
			log.info(e.getMessage());
		} catch (NoSuchMethodException e) {
			log.info(e.getMessage());
		} catch (IllegalArgumentException e) {
			log.info(e.getMessage());
		} catch (IllegalAccessException e) {
			log.info(e.getMessage());
		} catch (InvocationTargetException e) {
			log.info(e.getMessage());
		}
		return null;
	}

	private static String buildName(String name, String prefix) {
		StringBuffer buffer = new StringBuffer();
		buffer.append(prefix);
		buffer.append(name.substring(0, 1).toUpperCase());
		buffer.append(name.substring(1));
		return buffer.toString();
	}

	public static boolean equals(String s1, String s2) {
		if (s1 != null&&s1.length() > 0)
			return s1.equals(s2);
		else if (s2 != null&&s2.length() > 0)
			return s2.equals(s1);
		else
			return true;
	}
	
	public static boolean equals(Object s1, Object s2) {
		if (s1 != null)
			return s1.equals(s2);
		return s2 == null;
	}
	
	public static void redirect(String url) {
        try {
            ServletActionContext.getResponse().sendRedirect(url);
            log.info("redirect to :" + url);
        } catch (IOException e) {
            log.info(e.getMessage());
        }
    }

	public static HttpServletResponse getHttpResponse() {
		return ServletActionContext.getResponse();
	}

	public static PageIndex createPageIndex(int pageSize) {
        PageIndex index = new PageIndex("", ServletActionContext.getRequest().getServletPath(),
                pageSize);
        index.setCurrentPage(getCurrentPageNumber());
        ActionUtil.setAttribute(ActionConstants.ATTR_KEY_PAGEINDEX, index);
        return index;
    }

    public static PageIndex createPageIndex() {
        return createPageIndex(10);
    }

    private static int getCurrentPageNumber() {
        String pageNum = ActionUtil.getRequestParameter(PageIndex.PAGE_NUM);
        if ((pageNum != null) && (!"".equals(pageNum))) {
            return Integer.parseInt(pageNum);
        }
        return 1;
    }

    public static String getIpAddress() {
        HttpServletRequest request = ServletActionContext.getRequest();
        String ip = request.getHeader("x-forwarded-for");
        if(ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader(PROXY_CLIENT_IP);
        }
        if(ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader(WL_PROXY_CLIENT_IP);
        }
        if(ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }
    
    private static final String TIME_FORMAT = "yy-MM-dd";

    /**
	 * get current time stamp
	 * @return
	 */
	public static String getCurrentTimeStamp(){
		Date date = new Date();
		SimpleDateFormat format = new SimpleDateFormat(TIME_FORMAT);
		return format.format(date);
	}

	public static boolean online() {
		User googleUser = (User) ActionUtil.getSession(SessionParameters.GOOGLE_USER);
		if(googleUser != null){
			return true;
		}
		return false;
	}

	public static User getCurrentUser() {
		UserService userService = UserServiceFactory.getUserService();
		return userService.getCurrentUser();
	}
}
